package file

import (
	"encoding/json"
	"net/http"
	"path/filepath"
	"sort"

	"chainmaker.org/chainmaker/smarteditor/conf"
	"chainmaker.org/chainmaker/smarteditor/session"
	"chainmaker.org/chainmaker/smarteditor/util"

	"github.com/88250/gulu"
)

// Use to find results sorting.
type foundPath struct {
	Path  string `json:"path"`
	score int
}

type foundPaths []*foundPath

func (f foundPaths) Len() int           { return len(f) }
func (f foundPaths) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
func (f foundPaths) Less(i, j int) bool { return f[i].score > f[j].score }

// FindHandler handles request of find files under the specified directory with the specified filename pattern.
func FindHandler(w http.ResponseWriter, r *http.Request) {
	httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
	if httpSession.IsNew {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}
	uid := httpSession.Values["uid"].(string)

	result := gulu.Ret.NewResult()
	defer gulu.Ret.RetResult(w, r, result)

	var args map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		log.Error(err)
		result.Code = -1
		return
	}

	path := args["path"].(string) // path of selected file in file tree
	if !gulu.Go.IsAPI(path) && !util.BelongsGoPath(path) && !session.CanAccess(uid, path) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	name := args["name"].(string)
	userWorkspace := conf.GetUserWorkspace(uid)
	workspaces := filepath.SplitList(userWorkspace)

	if "" != path && !gulu.File.IsDir(path) {
		path = filepath.Dir(path)
	}

	founds := foundPaths{}

	for _, workspace := range workspaces {
		rs := find(workspace+conf.PathSeparator+"src", name, []*string{})

		for _, r := range rs {
			substr := gulu.Str.LCS(path, *r)

			founds = append(founds, &foundPath{Path: filepath.ToSlash(*r), score: len(substr)})
		}
	}
	sort.Sort(founds)
	result.Data = founds
}
